package com.it.tydic.estate.common.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.it.tydic.estate.common.aop.CodeMsg;
import com.it.tydic.estate.common.aop.Result;
import com.it.tydic.estate.common.constants.Constants;
import com.it.tydic.estate.common.util.*;
import com.it.tydic.estate.module.model.inner.TbLoginLog;
import com.it.tydic.estate.module.model.inner.TbUser;
import com.it.tydic.estate.module.service.RedisCacheService;
import com.it.tydic.estate.module.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.security.Principal;
import java.util.*;

@Configuration
@EnableWebSecurity
public class LoginSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {

	@Autowired
	private UserService userService;

	@Autowired
	private RedisCacheService redisCacheService;


	@Override
	public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
										Authentication authentication) throws IOException, ServletException {
		// 获得授权后可得到用户信息 可使用OperatorInfoService进行数据库操作
		/* */
		// 输出登录提示信息
		org.springframework.security.core.userdetails.User user=(org.springframework.security.core.userdetails.User)authentication.getPrincipal();
		TbUser tbUser=userService.findByUserName(user.getUsername());
		Map<String,Object> dataMap=new HashMap<>();
		response.setContentType("application/json;charset=utf-8");
		PrintWriter out=response.getWriter();
		ObjectMapper objectMapper=new ObjectMapper();
		if(tbUser != null && tbUser.getStatus()== 0 ){
			saveLogin(tbUser,request);
			SecurityContextHolder.getContext().setAuthentication(authentication);
			HttpSession session=request.getSession();
			session.setAttribute("user", user);
			session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); // 这个非常重要，否则验证后将无法登陆
			session.setAttribute(Constants.CURRENTUSER, tbUser);
			List<String> roleIds=userService.findRolesByUserId(tbUser.getUserId());
			tbUser.setRoleIds(roleIds);
			tbUser.setUserPassward(null);
			dataMap.put("user",tbUser);
			dataMap.put("userDetail",user);
			dataMap.put("tokenManager",generateToken(session));
			out.write(objectMapper.writeValueAsString(Result.success(dataMap)));
		}else{
			out.write(objectMapper.writeValueAsString(Result.error(CodeMsg.LOGIN_FORBIDDEN)));
		}
		out.flush();
		out.close();
	}

	/**
	 * 登陆与授权.
	 * @return
	 */
	private TokenManager generateToken(HttpSession session) {
		String accessToken=UUID.randomUUID()+"";
		String refreshToken=UUID.randomUUID()+"";
		TokenManager tokenManager=new TokenManager();
		tokenManager.setAccessToken(accessToken);
		tokenManager.setRefreshToken(refreshToken);
		tokenManager.setExpiresIn(30L);
		tokenManager.setTokenType("bearer");
		boolean flag=redisCacheService.set(session.getId(),tokenManager,Long.valueOf(30));
		System.out.println(flag);
		System.out.println(redisCacheService.get(session.getId()));
		return tokenManager;
	}



	// 记录登录日志
	public void saveLogin(TbUser user, HttpServletRequest request) {
		// 添加登录日志
		TbLoginLog loginLog = new TbLoginLog();
		InstaIdGenerator idGenerator = new InstaIdGenerator();
		loginLog.setId(idGenerator.nextId(TimeUtil.timeGen())+"");
		loginLog.setUserId(user.getUserId());
		loginLog.setUserName(user.getUserName());
		String ip = IPUtil.getIp(request);
		loginLog.setLoginIp(ip);
		loginLog.setCreateTime(new Date());
		loginLog.setSessionId(request.getSession().getId());
		loginLog.setUserAgen(request.getHeader("User-Agent"));
		Constants.loginLogQueue.offer(loginLog);
	}
}
